#!/bin/bash

# ==============================
# OpenSSH 自动升级脚本
# 适用于 Debian/Ubuntu & CentOS/RHEL
# ==============================

# 变量定义
OPENSSH_VERSION="9.6p1"  # 这里可以修改为最新的 OpenSSH 版本
OPENSSL_VERSION="1.1.1w" # OpenSSL 版本
INSTALL_DIR="/usr/local"
BACKUP_DIR="/root/openssh_backup"
LOG_FILE="/var/log/openssh_update.log"

# 日志记录函数
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a "$LOG_FILE"
}

# 确保以 root 用户运行
if [[ $(id -u) -ne 0 ]]; then
    log "错误: 请使用 root 用户运行此脚本"
    exit 1
fi

# 检测当前 OpenSSH 版本
CURRENT_VERSION=$(ssh -V 2>&1 | awk '{print $1, $2}')
log "当前 OpenSSH 版本: $CURRENT_VERSION"

# 更新系统并安装依赖
install_dependencies() {
    log "安装依赖包..."
    if [[ -f /etc/debian_version ]]; then
        apt update && apt install -y build-essential zlib1g-dev libssl-dev libpam0g-dev wget curl tar
    elif [[ -f /etc/redhat-release ]]; then
        yum groupinstall -y "Development Tools"
        yum install -y gcc make zlib-devel openssl-devel pam-devel wget curl tar
    else
        log "错误: 不支持的操作系统"
        exit 1
    fi
}

# 备份旧的 OpenSSH
backup_old_openssh() {
    log "备份当前 OpenSSH..."
    mkdir -p "$BACKUP_DIR"
    cp -r /etc/ssh "$BACKUP_DIR/ssh_config_backup_$(date '+%Y%m%d%H%M%S')"
    cp "$(command -v sshd)" "$BACKUP_DIR/sshd_backup_$(date '+%Y%m%d%H%M%S')"
}

# 下载和编译 OpenSSL（如果有需要）
install_openssl() {
    log "检查 OpenSSL 版本..."
    INSTALLED_OPENSSL=$(openssl version 2>/dev/null | awk '{print $2}')
    
    if [[ "$INSTALLED_OPENSSL" == "$OPENSSL_VERSION" ]]; then
        log "OpenSSL 已是最新版本 ($INSTALLED_OPENSSL)，跳过更新"
        return
    fi

    log "下载并安装 OpenSSL $OPENSSL_VERSION..."
    cd /usr/local/src || exit 1
    wget -q https://www.openssl.org/source/openssl-$OPENSSL_VERSION.tar.gz
    tar xzf openssl-$OPENSSL_VERSION.tar.gz
    cd openssl-$OPENSSL_VERSION || exit 1
    ./config --prefix="$INSTALL_DIR/openssl" --openssldir=/etc/ssl --shared
    make -j$(nproc) && make install

    # 设置新 OpenSSL 环境变量
    echo "$INSTALL_DIR/openssl/lib" > /etc/ld.so.conf.d/openssl.conf
    ldconfig
    log "OpenSSL $OPENSSL_VERSION 安装完成"
}

# 下载和编译 OpenSSH
install_openssh() {
    log "下载并安装 OpenSSH $OPENSSH_VERSION..."
    cd /usr/local/src || exit 1
    wget -q https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-$OPENSSH_VERSION.tar.gz
    tar xzf openssh-$OPENSSH_VERSION.tar.gz
    cd openssh-$OPENSSH_VERSION || exit 1

    ./configure --prefix="$INSTALL_DIR/openssh" --sysconfdir=/etc/ssh \
        --with-md5-passwords --with-pam --with-zlib --with-ssl-dir="$INSTALL_DIR/openssl"
    make -j$(nproc) && make install

    log "OpenSSH $OPENSSH_VERSION 安装完成"
}

# 更新 SSH 服务配置
update_ssh_config() {
    log "更新 SSH 配置..."
    
    # 确保配置文件不会被覆盖
    cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

    # 确保 OpenSSH 进程使用新安装的二进制文件
    if ! grep -q "/usr/local/openssh/sbin" /etc/environment; then
        echo "PATH=/usr/local/openssh/sbin:$PATH" >> /etc/environment
    fi

    # 重新加载 systemd 配置
    systemctl daemon-reexec
}

# 重启 SSH 服务
restart_ssh_service() {
    log "重启 SSH 服务..."
    
    # 确保新版本 SSH 可用后再重启
    if [[ -f /usr/local/openssh/sbin/sshd ]]; then
        systemctl restart sshd
        log "SSH 服务已重启"
    else
        log "错误: SSH 启动失败，请检查日志"
        exit 1
    fi
}

# 清理临时文件
clean_up() {
    log "清理临时文件..."
    rm -rf /usr/local/src/openssh*
    rm -rf /usr/local/src/openssl*
}

# 执行升级流程
main() {
    install_dependencies
    backup_old_openssh
    install_openssl
    install_openssh
    update_ssh_config
    restart_ssh_service
    clean_up
    log "OpenSSH $OPENSSH_VERSION 更新完成！"
}

# 开始执行脚本
main